﻿using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Input;
using System.Windows.Media;
using System.Windows.Shapes;

namespace Zero.UControl.Component
{
    [TemplatePart(Name = "RootGrid", Type = typeof(Grid))]
    [TemplatePart(Name = "SliderHandleH", Type = typeof(Grid))]
    [TemplatePart(Name = "SliderHandleV", Type = typeof(Grid))]
    [TemplatePart(Name = "Gradient", Type = typeof(LinearGradientBrush))]
    [TemplatePart(Name = "Stop0", Type = typeof(GradientStop))]
    [TemplatePart(Name = "Stop1", Type = typeof(GradientStop))]
    [TemplatePart(Name = "StrokeRectH", Type = typeof(Rectangle))]
    [TemplatePart(Name = "StrokeRectV", Type = typeof(Rectangle))]
    public class CompareSpliter : ContentControl
    {
        static CompareSpliter()
        {
            DefaultStyleKeyProperty.OverrideMetadata(typeof(CompareSpliter), new FrameworkPropertyMetadata(typeof(CompareSpliter)));
        }

        public CompareSpliter()
        {
            SizeChanged += CompareSpliter_SizeChanged;
        }

        #region 属性
        public Grid RootGrid { get; set; }
        public LinearGradientBrush Gradient { get; set; }
        public GradientStop Stop0 { get; set; }
        public GradientStop Stop1 { get; set; }
        public Grid SliderHandleH { get; set; }
        public Grid SliderHandleV { get; set; }
        public Rectangle StrokeRectH { get; set; }
        public Rectangle StrokeRectV { get; set; }
        #endregion

        #region 依赖属性
        public Brush MaskColor
        {
            get { return (Brush)GetValue(MaskColorProperty); }
            set { SetValue(MaskColorProperty, value); }
        }

        public static readonly DependencyProperty MaskColorProperty =
            DependencyProperty.Register("MaskColor", typeof(Brush), typeof(CompareSpliter), new PropertyMetadata(new SolidColorBrush((Color)ColorConverter.ConvertFromString("#8FFF"))));


        public SplitDirection Direction
        {
            get { return (SplitDirection)GetValue(DirectionProperty); }
            set { SetValue(DirectionProperty, value); }
        }

        public static readonly DependencyProperty DirectionProperty =
            DependencyProperty.Register("Direction", typeof(SplitDirection), typeof(CompareSpliter),
                new PropertyMetadata(SplitDirection.Horizontal, OnDirectionChanged));

        #endregion

        #region 依赖属性方法
        private static void OnDirectionChanged(DependencyObject d, DependencyPropertyChangedEventArgs e)
        {
            var oldDir = (SplitDirection)e.OldValue;
            var newDir = (SplitDirection)e.NewValue;
            if (oldDir != newDir)
            {
                var spliter = d as CompareSpliter;
                if (spliter == null || !spliter.isApplyTemplate)
                    return;
                spliter.UpdateLayout(newDir);
            }
        }

        private void UpdateLayout(SplitDirection newDir)
        {
            switch (newDir)
            {
                case SplitDirection.Horizontal:
                    Gradient.StartPoint = new Point(0, 0);
                    Gradient.EndPoint = new Point(1, 0);
                    SliderHandleH.HorizontalAlignment = HorizontalAlignment.Left;
                    SliderHandleH.VerticalAlignment = VerticalAlignment.Center;
                    SliderHandleH.Width = 2;
                    SliderHandleH.Cursor = Cursors.SizeWE;
                    StrokeRectH.Width = 2;
                    RootGrid.Dispatcher.BeginInvoke(() =>
                    {
                        SliderHandleH.Height = RootGrid.ActualHeight;
                        StrokeRectH.Height = RootGrid.ActualHeight;
                    },System.Windows.Threading.DispatcherPriority.Loaded);
                    break;
                case SplitDirection.Vertical:
                    Gradient.StartPoint = new Point(0, 1);
                    Gradient.EndPoint = new Point(0, 0);
                    SliderHandleV.HorizontalAlignment = HorizontalAlignment.Center;
                    SliderHandleV.VerticalAlignment = VerticalAlignment.Top;
                    SliderHandleV.Height = 2;
                    SliderHandleV.Cursor = Cursors.SizeNS;
                    StrokeRectV.Height = 2;
                    RootGrid.Dispatcher.BeginInvoke(() =>
                    {
                        SliderHandleV.Width = RootGrid.ActualWidth;
                        StrokeRectV.Width = RootGrid.ActualWidth;
                    },System.Windows.Threading.DispatcherPriority.Loaded);
                    break;
                default:
                    break;
            }
        }

        #endregion

        #region 事件
        private bool isApplyTemplate = false;
        public override void OnApplyTemplate()
        {
            base.OnApplyTemplate();
            RootGrid = GetTemplateChildSafe<Grid>("RootGrid");
            SliderHandleH = GetTemplateChildSafe<Grid>("SliderHandleH");
            SliderHandleV = GetTemplateChildSafe<Grid>("SliderHandleV");
            StrokeRectH = GetTemplateChildSafe<Rectangle>("StrokeRectH");
            StrokeRectV = GetTemplateChildSafe<Rectangle>("StrokeRectV");
            Gradient = GetTemplateChildSafe<LinearGradientBrush>("Gradient");
            Stop0 = GetTemplateChildSafe<GradientStop>("Stop0");
            Stop1 = GetTemplateChildSafe<GradientStop>("Stop1");

            if (SliderHandleH != null && SliderHandleV != null)
            {
                SliderHandleH.MouseDown -= SliderHandle_MouseDown;
                SliderHandleH.MouseMove -= SliderHandle_MouseMove;
                SliderHandleH.MouseUp -= SliderHandle_MouseUp;
                SliderHandleV.MouseDown -= SliderHandle_MouseDown;
                SliderHandleV.MouseMove -= SliderHandle_MouseMove;
                SliderHandleV.MouseUp -= SliderHandle_MouseUp;

                SliderHandleH.MouseDown += SliderHandle_MouseDown;
                SliderHandleH.MouseMove += SliderHandle_MouseMove;
                SliderHandleH.MouseUp += SliderHandle_MouseUp;
                SliderHandleV.MouseDown += SliderHandle_MouseDown;
                SliderHandleV.MouseMove += SliderHandle_MouseMove;
                SliderHandleV.MouseUp += SliderHandle_MouseUp;
            }
            isApplyTemplate = true;
            UpdateLayout(Direction);
        }

        private T GetTemplateChildSafe<T>(string name) where T : DependencyObject
        {
            var child = GetTemplateChild(name);
            if (child == null)
                throw new InvalidOperationException($"模板中未找到名为 {name} 的元素。");
            return child as T;
        }

        private void CompareSpliter_SizeChanged(object sender, SizeChangedEventArgs e)
        {
            if (Stop0 != null)
            {
                double offset = Stop0.Offset;
                if (Direction == SplitDirection.Horizontal)
                {
                    var position = Math.Round((RootGrid.ActualWidth - 2) * offset, 3);
                    SliderHandleH.Margin = new Thickness(position, 0, 0, 0);
                }
                else if (Direction == SplitDirection.Vertical)
                {
                    var position = Math.Round((RootGrid.ActualHeight - 2) * offset, 3);
                    SliderHandleV.Margin = new Thickness(0, position, 0, 0);
                }
            }
        }

        private bool isDragging = false;

        private void SliderHandle_MouseDown(object sender, MouseButtonEventArgs e)
        {
            isDragging = true;
            if (Direction == SplitDirection.Horizontal)
                SliderHandleH.CaptureMouse();
            else
                SliderHandleV.CaptureMouse();
        }

        private void SliderHandle_MouseMove(object sender, MouseEventArgs e)
        {
            if (isDragging)
            {
                var posX = e.GetPosition(RootGrid).X;
                var posY = e.GetPosition(RootGrid).Y;

                if (Direction == SplitDirection.Horizontal)
                {
                    posX = Math.Max(0, Math.Min(posX, RootGrid.ActualWidth - StrokeRectH.ActualWidth));
                    SliderHandleH.Margin = new Thickness(posX, 0, 0, 0);
                    var rate = posX / (RootGrid.ActualWidth - StrokeRectH.ActualWidth);
                    double offset = Math.Round(rate, 3);
                    Stop0.Offset = offset;
                    Stop1.Offset = offset;
                }
                else if (Direction == SplitDirection.Vertical)
                {
                    posY = Math.Max(0, Math.Min(posY, RootGrid.ActualHeight - StrokeRectV.ActualHeight));
                    Debug.WriteLine($"posY: {posY}");
                    SliderHandleV.Margin = new Thickness(0, posY, 0, 0);
                    var rate = posY / (RootGrid.ActualHeight - StrokeRectV.ActualHeight);
                    double offset = Math.Round(rate, 3);
                    Stop0.Offset = 1 - offset;
                    Stop1.Offset = 1 - offset;
                }
            }
        }

        private void SliderHandle_MouseUp(object sender, MouseButtonEventArgs e)
        {
            isDragging = false;
            if (Direction == SplitDirection.Horizontal)
                SliderHandleH.ReleaseMouseCapture();
            else
                SliderHandleV.ReleaseMouseCapture();
        }
        #endregion
    }

    public enum SplitDirection
    {
        Horizontal,
        Vertical
    }
}
